/*********************************************/

// 次文件只需要关注 getBars 和 subscribeBars 函数即可

/******************************************/

// 历史数据 第一条数据的 时间撮 因为k线图一次性历史数据只拿一部分，用户吧图往前滑动，就会用这个时间撮去请求更早的 历史数据
var detafeed_historyTime = 0
// 上一次的 K线周期 切换产品的时候 需要从websock 取消订阅这个
var detafeed_lastResolution = null
// 上一次的产品 切换产品的时候 需要从websock 取消订阅这个
var detafeed_lastSymbol = null

var cacheData = {}
var intervalGL = 1
var getBarTimer = null
var symbolCode = null
var lastTime = null

var runtime = {
	period: 'm1',
	interval: 1,
	cacheData: {},
	symbolCode: null,
	getBarTimer: null,
	lastTime: null,	
}

function FeedBase(pr) {
	// this.pr = pr
	// this.symbolInfo = pr.stock
}

FeedBase.prototype.onReady = function(callback) {
	setTimeout(function() {
		callback(this._configuration)
	}, 0)
}

FeedBase.prototype.getSendSymbolName = function(symbolName) {
	var name = symbolName.split('/')
	return (name[0] + name[1]).toLocaleLowerCase()
}

FeedBase.prototype.resolveSymbol = function(symbolName, onResolve, onError) {
	setTimeout(function() {
		runtime.symbolCode = symbolName
		onResolve({
			name: symbolName,
			timezone: "Asia/Shanghai", // UTC/GMT
			minmov: 1,
			minmov2: 0,
			pricescale: 100,
			pointvalue: 1,
			ticker: symbolName,
			description: "",
			// session: "24x7",
			// regular_session: "24x7",
			session: '0930-1500',
			type: "stock",
			format: 'price',
			volume_precision: 10,
			has_empty_bars: true,
			has_intraday: true,
			intraday_multipliers: ['1', '5', '15', '30', '60', '240', '1D', '1W'], // 时间
			// supportedResolutions: ['1', '5', '15', '30', '60', '240', '1D', '1W'],
			has_weekly_and_monthly: false, // 是否有周线和月线
			has_no_volume: false, // 是否拥有成交量数据。
		})
	}, 0)
}

/**
 * 更多时间类型在这里添加 时间类型请看火币文档
 * @param resolution  订阅周期 按照自己喜欢的来 如 30 30分钟、 1D 一天 
 * @param name 交易对symbol
 * @param to 结束时间
 * @returns {object}
 */
const resolutionFormat = (resolution, name, to) => {
	let req = `sub.futures.kline`;
	let minutes = 'm'+ resolution;
	
	if (resolution.includes('D')) {
		if (resolution.length < 2) resolution = '1' + resolution;
		req = `sub.futures.kline`;
		minutes = `${resolution}d`;
		// minutes = parseInt(resolution) * 24 * 60;
	} else if (resolution.includes('W')) {
		if (resolution.length < 2) resolution = '1' + resolution;
		req = `sub.futures.kline`;
		minutes = `week`;
		// minutes = parseInt(resolution) * 24 * 60 * 7;
	} else if (resolution.includes('M')) {
		if (resolution.length < 2) resolution = '1' + resolution;
		req = `sub.futures.kline`;
		minutes = `month`;
		// minutes = parseInt(resolution) * 24 * 60 * 30;
	} else {
		if (resolution / 60 > 1) {
			req = `sub.futures.kline`;
			minutes = `${resolution / 60}h`;
		}
	}
	let code = name;
	let from = null;
	if (to) {
		from = to - 200 * minutes * 60;
		if (resolution.includes('M') || resolution.includes('W')) { // 周线月线控制条数，时间超出火币规定范围, ws报错
			from = to - 50 * minutes * 60;
		}
	}
	return {
		minutes,
		req,
		from,
		to,
		code,
	};
};

function initLimit(resolution, rangeStartDate, rangeEndDate) {
	var limit = 0
	let minutes = 'm'+ resolution;
	
	if (resolution.includes('D')) {
		if (resolution.length < 2) {
			resolution = '1' + resolution;
		}
		minutes = `${resolution}`;
	} else if (resolution.includes('W')) {
		if (resolution.length < 2) {
			resolution = '1' + resolution;
		}
		minutes = `W`;
		// minutes = parseInt(resolution) * 24 * 60 * 7;
	} else if (resolution.includes('M')) {
		if (resolution.length < 2) {
			resolution = '1' + resolution;
		}
		minutes = `M`;
	} else {
		if (resolution / 60 > 1) {
			minutes = `${resolution / 60}h`;
		}
	}
	
	return minutes
	
	/*
	switch (resolution) {
		case '1D': limit = Math.ceil((rangeEndDate - rangeStartDate) / 60 / 60 / 24); break
		case '1W': limit = Math.ceil((rangeEndDate - rangeStartDate) / 60 / 60 / 24 / 7); break
		case '1M': limit = Math.ceil((rangeEndDate - rangeStartDate) / 60 / 60 / 24 / 31); break
		default: limit = Math.ceil((rangeEndDate - rangeStartDate) / 60 / resolution); break
	}*/
	return limit
};

function unSubscribe(interval, symbol, period) {
	// 停止订阅，删除过期缓存、缓存时间、缓存状态
	runtime.interval = interval
	var ticker = symbol + '-' + interval
	var tickertime = ticker + 'load'
	var tickerstate = ticker + 'state'
	var tickerCallback = ticker + 'Callback'
	
	delete runtime.cacheData[ticker]
	delete runtime.cacheData[tickertime]
	delete runtime.cacheData[tickerstate]
	delete runtime.cacheData[tickerCallback]
	
	socket.sendMsg({
		event: 'unsub.futures.kline',
		data: {
			code: symbol,
			period: period,
		}
	})
};

function initMessage(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback) {
	// console.log('发起请求，从websocket获取当前时间段的数据');
	var ticker = symbolInfo.name + '-' + resolution
	// 保留当前回调
	var tickerCallback = ticker + 'Callback'
	runtime.cacheData[tickerCallback] = onLoadedCallback
	
	// 获取需要请求的数据数目
	var period = initLimit(resolution, rangeStartDate, rangeEndDate)

	// 商品名
	var symbol = symbolInfo.name
	// 如果当前时间节点已经改变，停止上一个时间节点的订阅，修改时间节点值
	if (runtime.interval != resolution) {
		unSubscribe(runtime.interval, symbolInfo.name, initLimit(''+ runtime.interval, rangeStartDate, rangeEndDate))
		runtime.interval = resolution
	}
	
	// 获取当前时间段的数据，在onMessage中执行回调onLoadedCallback
	socket.sendMsg({
		event: 'sub.futures.kline',
		data: {
			code: symbolInfo.name,
			period: period,
		}
	})
}

function getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback, onError) {

}

FeedBase.prototype.getBars = function(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback) {
	runtime.symbolCode = symbolInfo.name
	var ticker = runtime.symbolCode + '-' + resolution
	var tickerload = ticker + 'load'
	var tickerstate = ticker + 'state'
	
	if (!runtime.cacheData[ticker] && !runtime.cacheData[tickerstate]) {
		// 如果缓存没有数据，而且未发出请求，记录当前节点开始时间
		runtime.cacheData[tickerload] = rangeStartDate
		// 发起请求，从websocket获取当前时间段的数据
		initMessage(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback)
		// 设置状态为true
		runtime.cacheData[tickerstate] = !0
		return false
	}
	
	// console.log(runtime.cacheData[tickerload], rangeStartDate)
	// return
	if (!runtime.cacheData[tickerload] || runtime.cacheData[tickerload] > rangeStartDate) {
		// 如果缓存有数据，但是没有当前时间段的数据，更新当前节点时间
		/*runtime.cacheData[tickerload] = rangeStartDate
		// 发起请求，从websocket获取当前时间段的数据
		initMessage(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback)
		// 设置状态为true
		runtime.cacheData[tickerstate] = !0*/
		return false
	}
	
	if (runtime.cacheData[tickerstate]) {
		// 正在从websocket获取数据，禁止一切操作
		return false
	}
	
	ticker = runtime.symbolCode + '-' + runtime.interval
	if (runtime.cacheData[ticker] && runtime.cacheData[ticker].length) {
		// isLoading = false
		var newBars = []
		runtime.cacheData[ticker].forEach(item => {
			if (item.time >= rangeStartDate * 1000 && item.time <= rangeEndDate * 1000) {
				newBars.push(item)
			}
		})
		
		onLoadedCallback(newBars)
	} else {
		/*getBarTimer = setTimeout(function() {
			getBars(symbolInfo, resolution, rangeStartDate, rangeEndDate, onLoadedCallback)
		}, 100)*/
	}
};


Event.off('data')
Event.on('data', data => {
	if (data && Array.isArray(data)) {
		
		var ticker = runtime.symbolCode + '-' + runtime.interval
		var tickerstate = ticker + 'state'
		var tickerCallback = ticker + 'Callback'
		var onLoadedCallback = runtime.cacheData[tickerCallback]
		
		let list = []
		data.forEach((i) => {
			list.push({
				time: i.time * 1000,
				// open: parseFloat(i.open),
				// high: parseFloat(i.high),
				// low: parseFloat(i.low),
				
				// low: parseFloat(i.avgPrice / 2),
				// open: parseFloat(i.unknown),
				high: Number(i.avgPrice),
				close: Number(i.close),
				volume: i.volume
			})
		})
		
		// 如果没有缓存数据，则直接填充，发起订阅
		if (!runtime.cacheData[ticker]) {
			runtime.cacheData[ticker] = list
		}
		
		// 新数据即当前时间段需要的数据，直接喂给图表插件
		if (onLoadedCallback) {
			onLoadedCallback(list)
			delete runtime.cacheData[tickerCallback]
		}
		
		// 请求完成，设置状态为false
		runtime.cacheData[tickerstate] = !1
		// 记录当前缓存时间，即数组最后一位的时间
		if (runtime.cacheData[ticker].length > 0) {
			lastTime = runtime.cacheData[ticker][runtime.cacheData[ticker].length - 1].time
		}
			
		
		
		
		/*
		var ticker = symbolCode + '-' + intervalGL
        var tickerstate = ticker + 'state'
		var tickerCallback = ticker + 'Callback'
		var onLoadedCallback = cacheData[tickerCallback]
		
		// 记录这次请求的时间周期
		// detafeed_lastResolution = resolution
		var meta = {
			noData: false
		}
		
		const list = []
		
		if (data.length) {
			for (let i of data) {
				i.time = i.time * 1000
				i.close = Number(i.close)
				i.avgPrice = Number(i.avgPrice)
				i.volume = i.volume
				list.push(i)
			}
		} else {
			meta = {
				noData: true
			}
		}
		
		list.sort((l, r) => (l.time > r.time ? 1 : -1));
		
		// 如果没有缓存数据，则直接填充，发起订阅
		if (!cacheData[ticker]) {
			cacheData[ticker] = list
		}
		
		
		// 新数据即当前时间段需要的数据，直接喂给图表插件
		if (onLoadedCallback) {
			onLoadedCallback(list, meta)
			delete cacheData[tickerCallback]
		}
		
		// 请求完成，设置状态为false
		cacheData[tickerstate] = !1
		// 记录当前缓存时间，即数组最后一位的时间
		if (cacheData[ticker].length > 0) {
			lastTime = cacheData[ticker][cacheData[ticker].length - 1].time
		}*/
	}
})



FeedBase.prototype.getBars222 = function(symbolInfo, resolution, rangeStartDate, rangeEndDate, onResult, onError) {
	/*if (!periodParams.firstDataRequest) {
		onResult([], { noData: true });
		return;
	}*/
	// console.log("FeedBase.prototype.getBars")
	// 切换产品周期 或者 切换产品 会执行这个函数
	// let reso = resolutionFormat(resolution, symbolInfo.name, rangeEndDate)
	let reso = resolutionFormat(resolution, symbolInfo.name, rangeEndDate > detafeed_historyTime ? rangeEndDate : detafeed_historyTime)
	// 是历史数据 
	var history = true
	/*
	  !detafeed_historyTime 如果没请请求过这个产品或者这个周期的历史数据
	  resolution !== detafeed_lastResolution 是否更换了产品周期
	  detafeed_lastSymbol !== symbolInfo.name 是否切换了产品
	*/
	if (!detafeed_historyTime || (resolution !== detafeed_lastResolution) || detafeed_lastSymbol !== symbolInfo.name) {
		// 那就不是历史数据
		history = false
		// 储存请求过的产品
		detafeed_lastSymbol = symbolInfo.name
		// 记录目前时间戳，就用目前时间戳往前请求历史数据
		// detafeed_historyTime = window.parseInt((Date.now() / 1000))
	}
	
	/*
	  @socket.sendData
	  第一个参数订阅历史数据
	  第二个参数订阅实时数据
	  第三个参数 是  是否是历史数据
	*/
	socket.sendData({
		req: reso.req,
		minutes: reso. minutes,
		code: reso.code,
		from: reso.from,
		to: reso.to,
	}, reso.req, history)

	Event.off('data')

	Event.on('data', data => {
		if (data && Array.isArray(data)) {
			// 记录这次请求的时间周期
			detafeed_lastResolution = resolution
			var meta = {
				noData: false
			}

			const datas = []
			if (data.length) {
				detafeed_historyTime = data[0].time
				detafeed_historyTime = data[0].time
				for (let i of data) {
					i.time = i.time * 1000
					i.close = Number(i.close)
					i.avgPrice = Number(i.avgPrice)
					i.volume = i.volume
					datas.push(i)
				}
			} else {
				meta = {
					noData: true
				}
			}
			
			datas.sort((l, r) => (l.time > r.time ? 1 : -1));
			
			onResult(datas, meta)
		}
	})
}

// 				subscribeBars
// symbolInfo:			object 			SymbolInfo
// resolution: 			string 			周期
// onTick: function(bar)  bar:object{time, close, open, high, low, volume}
// listenerGuid: 		object
// onResetCacheNeededCallback(从1.7开始): function()将在bars数据发生变化时执行
FeedBase.prototype.subscribeBars = function(symbolInfo, resolution, onTick, listenerGuid, onResetCacheNeededCallback) {
	Event.off('realTime')
	// 拿到实时数据 在这里画
	Event.on('realTime', data => {
		// console.log(Object.prototype.toString.call(data))
		// if (Object.prototype.toString.call(data) === '[object Object]' && data.hasOwnProperty('open')) {
		if (Object.prototype.toString.call(data) === '[object Array]' && data.hasOwnProperty('open')) {
			// 当您调用onTick且K线时间等于最新K线时间时，那么这条最新K线将被您传入的K线所替换
			// 例:
			// 最近一条K线为 {1419411578413, 10, 12, 9, 11}
			// 调用 onTick({1419411578413, 10, 14, 9, 14})
			// 图表库通过时间1419411578413找出K线，已存在并且是最近的那一个
			// 图表库替换K线，因此现在最近一条K线为 {1419411578413, 10, 14, 9, 14}
			// 现在，在图表接收到数据后，没有办法改变历史上的K线
			onTick({
				time: Number(data.time) * 1000,
				close: Number(data.close),
				open: Number(data.open),
				high: Number(data.high),
				low: Number(data.low),
				volume: Number(data.volume)
			})
		}
	})
}


// listenerGuid:object
// 取消订阅K线数据。在调用subscribeBars方法时,图表库将跳过与listenerGuid相同的对象。
FeedBase.prototype.unsubscribeBars = function(listenerGuid) {
	// 取消订阅产品的callback
}
